#ifndef _BATTLECITY_GAME_H_
#define _BATTLECITY_GAME_H_

#include "game.h"
#include "widget.h"
#include "model.h"
#include "matrix.h"
#include "xml.h"
#include "camera.h"
#include "sprite.h"
#include "physycs.h"
#include "particles.h"
#include "resourcemngr.h"
#include "font.h"
#include "gui.h"
#include <map>
#include <list>
#include <string>

using namespace std;

class battlecity_menu: public widget
{
public:
	void create();
	void destroy();
	void update(u32 _dt);
	void draw();

	void event_keyboard(u32 _type,u32 _key);
	void event_mouse(u32 _type,u32 _x,u32 _y,u32 _keys);

	void show();

private:
	static void  _callback(void* _cls,gui_event _e);
	model*   m_menu_scene;
	//model*   barrel;
	camera*  m_camera;
	matrix4  m_projection;
	guimngr* m_guimngr;
	texture* m_cursor_tex;
	resourcemngr* m_resmngr;
	sprite m_cursor;
	font*    m_font;
};

class battlecity_level;
class battlecity_bullet;

enum object_type
{
	ot_player,
	ot_enemy,
	ot_level
};

class battlecity_object
{
public:
	battlecity_object(battlecity_level* _parent);
	virtual ~battlecity_object(){}

	void load(model* _mdl,xml_node& _node);

	virtual void draw(){}
	virtual void update(u32 _dt){}

	virtual void bullet_collide(battlecity_bullet& _bul)=0;

	vector3& get_pos(){return m_position;}
	collider* get_collider()
	{
		if(!m_collider)
			return 0;
		m_collider->set_pos(m_position);
		return m_collider;
	}
	string		 get_id(){return m_id;}
	object_type  get_type(){return m_type;}

protected:
	matrix4 m_world;
	vector3 m_position;

	float	m_dir;

	render* m_render;

	battlecity_level* m_parent;

	model* m_model;
	string m_chunk;

	string m_id;

	object_type m_type;

	collider* m_collider;
};

class battlecity_static: public battlecity_object
{
public:
	battlecity_static(battlecity_level* _parent):battlecity_object(_parent){m_type=ot_level;}
	virtual	~battlecity_static();

	virtual void load(model* _mdl,xml_node& _node);
	virtual void draw();
	virtual void update(u32 _dt);

	virtual void bullet_collide(battlecity_bullet& _bul){}

};

enum tank_state
{
	st_rotate,
	st_move,
	st_stay,
	st_dead,
};

class battlecity_tank: public battlecity_object
{
public:
	battlecity_tank(battlecity_level* _parent);
	virtual ~battlecity_tank();

	virtual void load(model* _mdl,xml_node& _node);

	virtual void update(u32 _dt);
	virtual void draw();

protected:
	float		   m_velocity;
	float		   m_next_dir;
	tank_state	   m_state;
	float		   m_tower_dir;

	float		   m_rot_speed;	 // Rad./sec.
	float		   m_accelerate; // 1/sec.
	float		   m_max_speed;  // 1/sec.

	float		   m_shot_delta;
	float		   m_shot_time;
};

class battlecity_player: public battlecity_tank
{
public:
	battlecity_player(battlecity_level* _parent):battlecity_tank(_parent){m_type = ot_player;}
	void update(u32 _dt);
	void load(model* _mdl,xml_node& _node);
	void bullet_collide(battlecity_bullet& _bul);
};

class battlecity_enemy: public battlecity_tank
{
public:
	battlecity_enemy(battlecity_level* _parent):battlecity_tank(_parent){m_type = ot_enemy;}
	void update(u32 _dt);
	void load(model* _mdl,xml_node& _node);
	void bullet_collide(battlecity_bullet& _bul);
private:
	u32 m_ai_timer;
	bool m_collide;

};

enum bullet_type
{
	bt_player,
	bt_enemy
};

class battlecity_bullet
{
public:
	battlecity_bullet()
	{
		m_isfree = true;
		m_livetime = 0;
		m_speed = 200.0f;
	}

	vector3 m_pos;
	vector3 m_vel;
	vector3 m_startpos;
	float m_maxdist;
	bool m_isfree;
	u32 m_livetime;
	bullet_type m_type;
	float m_speed;// 1/sec
};

class battlecity_level
{
public:
	battlecity_level();
	~battlecity_level();

	void load(const char* _fname);

	void draw();
	void update(u32 _dt);

	battlecity_player* get_player();

	void add_bullet(bullet_type _bt,vector3 _pos, vector3 _vel, float _maxdist);

	list<battlecity_object*>& get_objects_vector()
	{
		return m_objects;
	}

	model* get_model(){return m_model;}

	exploser*     m_tank_exploser;
	resourcemngr* m_resmngr;

private:

	list<battlecity_object*> m_objects;
	battlecity_bullet m_bullets[1024];
	exploser* m_bullet_exploser;
	texture* m_explose_tex_bul;
	texture* m_explose_tex_tank;
	model* m_bullet_mdl;

	battlecity_player* m_player;
	matrix4 m_world;

	model* m_model;
	string m_chunk;

	render* m_render;
	sprite m_cursor;
	texture* m_cursor_tex;
};

class battlecity_gameplay: public widget
{
public:

	void create();
	void destroy();

	void update(u32 _dt);
	void draw();

	void show();

	void event_keyboard(u32 _type,u32 _key);
	void event_mouse(u32 _x,u32 _y,u32 _keys);

private:
	list<battlecity_level*> m_levels;
	battlecity_level* m_curr_level;
	battlecity_player* m_player;
	matrix4 m_projection;

	resourcemngr* m_resmngr;

	float m_camera_height;
	font*    m_font;
};

class battlecity_game: public game
{
public:
	void create(xml_node& _node);
	void destroy();
};

#endif